/*--------------------------------------------- Noble Steed Engine--------------------------------------*
Authors : Daniel Randle, Alex Bourne
Date Created : Mar 13 2013

File:
	nsobject.cpp

Description:
	This file contains the definition for the NSObject class and any associated functions that help
	the ol' girl out
*-----------------------------------------------------------------------------------------------------*/

#include <nsobject.h>
#include <logfile.h>
#include <sstream>
#include <nscamera.h>
#include <nsmaparea.h>
#include <nsobjectreference.h>
#include <map>
#include <vector>

#ifdef DEBUG
#include <debug.h>
#endif

/*---------------------------*
|   class NSObject BEGINS  |
*---------------------------*/

NSObject::NSObject(const std::string & name, const std::string & mfileName, const std::string & mDirectory, const std::string tDirectory, bool shadows, bool hasTransluscentMaterial):
	objectName(name),
	meshFileName(mfileName),
	meshDir(mDirectory),
	textureDir(tDirectory),
	mesh(NULL),
	castShadows(shadows),
	objType(Base),
	copiesInSet(0)
{
	std::stringstream ss;
	objectID = objectCount;
	ss << "Creating base object with name " << name << " and ID " << objectID;
	LogFile l(ss);
	if ( (mfileName != "") && (mDirectory != "") && (tDirectory != "") )
	{
		if (!loadMesh(mfileName, mDirectory, tDirectory,hasTransluscentMaterial))
			l.write("Error loading object with name : " + objectName);
	}
	++objectCount;
	instanceTransforms = new std::vector<NSMatrix4Df>();
}

NSObject::~NSObject()
{
	std::stringstream ss;
	ss << "Deleting object with name " << objectName << " and ID " << objectID;
	LogFile l(ss);
	delete mesh;
	l.write("Object Deleted");
	delete instanceTransforms;
}

void NSObject::addCopy()
{
	++copiesInSet;
}

void NSObject::addInstanceTransform(const NSMatrix4Df & totalTransform)
{
	instanceTransforms->push_back(totalTransform);
}

unsigned int NSObject::getCopies() const
{
	return copiesInSet;
}

unsigned int NSObject::getID() const
{
	return objectID;
}

unsigned int NSObject::getInstanceCount() const
{
	return instanceTransforms->size();
}

const NSMesh * NSObject::getMesh() const
{
	return mesh;
}

std::string NSObject::getName() const
{
	return objectName;
}

NSObject::ObjectType NSObject::getObjectType() const
{
	return objType;
}

NSMatrix4Df & NSObject::instanceTransMat(unsigned int referenceID)
{
	return (*instanceTransforms)[referenceID];
}

bool NSObject::isCastShadows() const
{
	return castShadows;
}

bool NSObject::isHasMesh() const
{
	return (mesh != NULL);
}

bool NSObject::isHasTransluscentMaterial() const
{
	if (mesh != NULL)
		return mesh->isHasTransMat();
	return false;
}

bool NSObject::loadMesh(const std::string & fileName, const std::string & meshDirect, const std::string & texDirect, bool hasTransMat)
{
	if (fileName != "")
		meshFileName = fileName;
	if (meshDirect != "")
		meshDir = meshDirect;
	if (texDirect != "")
		textureDir = texDirect;

	mesh = new NSMesh("","",hasTransMat);
	
	std::string fullPath = meshDir + "/" + meshFileName.substr(meshFileName.find_last_of("/\\")+1);
	if (!mesh->loadScene(fullPath.c_str(), textureDir))
	{
		LogFile("Error initializing mesh in NSObject");
		return false;
	}
	return true;
}

bool NSObject::removeCopy()
{
	if (copiesInSet > 0)
	{
		--copiesInSet;
		return true;
	}
	return false;
}

void NSObject::removeInstanceTransform(unsigned int referenceID)
{
	if (referenceID >= instanceTransforms->size() )
	{
		LogFile("Trying to remove instance transform with invalid referenceID");
		return;
	}
	std::vector<NSMatrix4Df>::iterator iter = (instanceTransforms->begin() + referenceID);
	instanceTransforms->erase(iter);
}

void NSObject::setCastShadows(bool cast)
{
	castShadows = cast;
}

void NSObject::setName(const std::string & name)
{
	objectName = name;
}

// Virtual Functions

void NSObject::draw()
{
	if (mesh != NULL)
		mesh->draw(instanceTransforms,true);
}

void NSObject::drawSingle(unsigned int refID)
{
	if (mesh != NULL && (*instanceTransforms)[refID].value(3,3) != 10.0f)
		mesh->drawSingle((*instanceTransforms)[refID],true);
}

// Static Functions

unsigned int NSObject::getObjectCount()
{
	return objectCount;
}


unsigned int NSObject::objectCount = 0;
